package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.OrdersPageQueryDTO;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.entity.*;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.AddressBookMapper;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.result.PageResult;
import com.sky.service.OrderService;
import com.sky.vo.MyOrderVO;
import com.sky.vo.OrderInfo;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.websocket.WebSocketServer;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    OrderMapper orderMapper;
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private WebSocketServer webSocketServer;

    @Override
    public OrderSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) {
        Long userId = BaseContext.getCurrentId();
        AddressBook addressBook = AddressBook.builder().userId(userId).build();
        List<AddressBook> list = addressBookMapper.list(addressBook);
        if (list.isEmpty()){
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        addressBook  = list.get(0);
        ShoppingCart shoppingCart = ShoppingCart.builder().userId(userId).build();
        List<ShoppingCart> list1 = shoppingCartMapper.selectByUserandDishorSetmeal(shoppingCart);
        if (list1.isEmpty()){
            throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO,orders);
        orders.setUserId(userId);
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(1);
        orders.setPhone(addressBook.getPhone());
        orders.setConsignee(addressBook.getConsignee());
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        orders.setStatus(2);
        orderMapper.insert(orders);

        List<OrderDetail> list2 = new ArrayList<>();
        for (ShoppingCart cart:list1){
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(cart,orderDetail);
            orderDetail.setOrderId(orders.getId());
            list2.add(orderDetail);
        }
        orderDetailMapper.insert(list2);
        shoppingCartMapper.deleteAllById(userId);
        OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder()
                .id(orders.getId())
                .orderNumber(orders.getNumber())
                .orderAmount(orders.getAmount())
                .orderTime(LocalDateTime.now())
                .build();
        return orderSubmitVO;
    }

    @Override
    public PageResult page(OrdersPageQueryDTO ordersPageQueryDTO) {
        Orders orders = Orders.builder()
                .status(ordersPageQueryDTO.getStatus())
                .build();
        PageHelper.startPage(ordersPageQueryDTO.getPage(),ordersPageQueryDTO.getPageSize());
        List<OrderInfo> listInfo = orderMapper.select(orders);
        List<MyOrderVO> myOrderVOList = OrderInfoToVO(listInfo);
        Long page = orderMapper.selectTotal(orders);
        PageResult pageResult  = new PageResult(page,myOrderVOList);
        return pageResult;
    }

    @Override
    public MyOrderVO orderDetail(Long id) {
        Orders orders = Orders.builder()
                .id(id)
                .build();
        List<OrderInfo> list = orderMapper.select(orders);
        List<MyOrderVO> myOrderVOList = OrderInfoToVO(list);
        return myOrderVOList.get(0);
    }

    @Override
    public void update(Orders orders) {
        orderMapper.update(orders);
    }

    @Override
    public void repetition(Long id) {
        List<OrderDetail> orderDetailList = orderMapper.selectDetail(id);
        List<ShoppingCart> shoppingCartList = new ArrayList<>();
        orderDetailList.forEach(e->{
            shoppingCartList.add(ShoppingCart.builder()
                            .name(e.getName())
                            .image(e.getImage())
                            .userId(BaseContext.getCurrentId())
                            .dishId(e.getDishId())
                            .setmealId(e.getSetmealId())
                            .dishFlavor(e.getDishFlavor())
                            .number(e.getNumber())
                            .amount(e.getAmount())
                            .createTime(LocalDateTime.now())
                            .build());
        });
        shoppingCartMapper.insertList(shoppingCartList);
    }

    @Override
    public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {

        PageHelper.startPage(ordersPageQueryDTO.getPage(),ordersPageQueryDTO.getPageSize());
        List<Orders> list = orderMapper.conditionSearchByPage(ordersPageQueryDTO);
        Page<Orders> page = (Page<Orders>) list;
        return new PageResult(page.getTotal(),list);
    }

    @Override
    public OrderStatisticsVO statistics() {

        Map<Integer,StatusCount> map = orderMapper.statistics();
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        map.entrySet().stream().forEach(e->{
            StatusCount statusCount = e.getValue();
            switch (statusCount.getStatus()){
                case 2:
                    orderStatisticsVO.setToBeConfirmed(statusCount.getCount());
                    break;
                case 3:
                    orderStatisticsVO.setConfirmed(statusCount.getCount());
                    break;
                case 4:
                    orderStatisticsVO.setDeliveryInProgress(statusCount.getCount());
                    break;
                }
        });
        return orderStatisticsVO;
    }

    @Override
    public void reminder(Long id) {
        Orders orders = Orders.builder().id(id).build();
        List<Orders> list = orderMapper.selectByOrder(orders);
        if (list.isEmpty()) throw  new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        orders = list.get(0);
        Map map = new HashMap<>();
        map.put("type",2);
        map.put("orderId",id);
        map.put("content","订单号:"+orders.getNumber());
        webSocketServer.sendToAllClient(JSON.toJSONString(map));
    }


    public MyOrderVO Orderset(OrderInfo orderInfo){
        MyOrderVO myOrderVO = new MyOrderVO();
        // 将订单基本信息从OrderInfo赋值到OrdersDTO
        myOrderVO.setId(orderInfo.getOrderId());
        myOrderVO.setNumber(orderInfo.getOrderNumber());
        myOrderVO.setStatus(orderInfo.getOrderStatus());
        myOrderVO.setUserId(orderInfo.getUserId());
        myOrderVO.setAddressBookId(orderInfo.getAddressBookId());
        myOrderVO.setOrderTime(orderInfo.getOrderTime());
        myOrderVO.setCheckoutTime(orderInfo.getCheckoutTime());
        myOrderVO.setPayMethod(orderInfo.getPayMethod());
        myOrderVO.setPayStatus(orderInfo.getPayStatus());
        myOrderVO.setAmount(orderInfo.getOrderAmount());
        myOrderVO.setRemark(orderInfo.getOrderRemark());
        myOrderVO.setUserName(orderInfo.getUserName());
        myOrderVO.setPhone(orderInfo.getUserPhone());
        myOrderVO.setAddress(orderInfo.getUserAddress());
        myOrderVO.setConsignee(orderInfo.getConsignee());
        myOrderVO.setCancelReason(orderInfo.getCancelReason());
        myOrderVO.setRejectionReason(orderInfo.getRejectionReason());
        myOrderVO.setCancelTime(orderInfo.getCancelTime());
        myOrderVO.setEstimatedDeliveryTime(orderInfo.getEstimatedDeliveryTime());
        myOrderVO.setDeliveryStatus(orderInfo.getDeliveryStatus());
        myOrderVO.setDeliveryTime(orderInfo.getDeliveryTime());
        myOrderVO.setPackAmount(orderInfo.getPackAmount());
        myOrderVO.setTablewareNumber(orderInfo.getTablewareNumber());
        myOrderVO.setTablewareStatus(orderInfo.getTablewareStatus());
        return myOrderVO;
    }

    public OrderDetail orderDetailset(OrderInfo orderInfo){
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setId(orderInfo.getOrderDetailId());
        orderDetail.setName(orderInfo.getDishName());
        orderDetail.setOrderId(orderInfo.getOrderDetailOrderId());
        orderDetail.setDishId(orderInfo.getDishId());
        orderDetail.setSetmealId(orderInfo.getSetmealId());
        orderDetail.setDishFlavor(orderInfo.getDishFlavor());
        orderDetail.setNumber(orderInfo.getDishNumber());
        orderDetail.setAmount(orderInfo.getDishAmount());
        orderDetail.setImage(orderInfo.getDishImage());
        return orderDetail;
    }

    public List<MyOrderVO> OrderInfoToVO(List<OrderInfo> listInfo){
        if (listInfo.isEmpty()) return null;
        List<MyOrderVO> listMyOrderVo = new ArrayList<>();
        MyOrderVO myOrderVO = Orderset(listInfo.get(0));
        listMyOrderVo.add(myOrderVO);
        for (int i=0;i<listInfo.size();i++){
            OrderInfo orderInfo = listInfo.get(i);
            myOrderVO = listMyOrderVo.get(listMyOrderVo.size()-1);
            if (myOrderVO.getId() != orderInfo.getOrderId()){
                myOrderVO = Orderset(orderInfo);
                listMyOrderVo.add(myOrderVO);
            }
            OrderDetail orderDetail = orderDetailset(orderInfo);
            List<OrderDetail> listOrderDetail = myOrderVO.getOrderDetailList();
            listOrderDetail.add(orderDetail);
            myOrderVO.setOrderDetailList(listOrderDetail);
            listMyOrderVo.set(listMyOrderVo.size()-1, myOrderVO);
        }
        return listMyOrderVo;
    }
}
